package com.whty.cms.filewps.util;

import com.qcloud.Module.Vod;
import com.qcloud.QcloudApiModuleCenter;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.auth.COSSigner;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.Copy;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.TransferManagerConfiguration;
import com.qcloud.cos.utils.UrlEncoderUtils;
import com.tencent.cloud.CosStsClient;
import com.whty.cms.filewps.common.constants.Consts;
import com.whty.cms.filewps.common.model.EsCospart;
import com.whty.cms.filewps.upload.dto.AttachFile;
import net.sf.json.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.HmacUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CosUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(CosUtil.class);
	private static String vodUrl = "https://vod.api.qcloud.com/v2/index.php?";
	private static String vodUrlNew = "https://mps.tencentcloudapi.com/?";  //新的转码接口地址
	private static String version = "2017-03-12";
	private static String algorithm = "TC3-HMAC-SHA256";
	private static String CHARSET = "UTF-8";
	private static COSClient cosClient;
	
	public static Map<String, Object> initiateMultipartUpload(AttachFile attach) throws CosClientException, CosServiceException{
		Map<String, Object> map = MapUtil.newHashMap();
		String fileExt = "";
		int idx = attach.getFileName().lastIndexOf(".");
		if (idx != -1) {
			fileExt = attach.getFileName().substring(idx + 1);
		}
		// 初始化分块
		cosClient = createCosClient();
		InitiateMultipartUploadRequest initRequest =
		                new InitiateMultipartUploadRequest(MemcacheUtil.getDatabaseObj(attach.getApplyType()+"-"+Consts.SOURCE_BUCKET), attach.getFilePath());
		ObjectMetadata meta = new ObjectMetadata();
		String contentType = Consts.contentTypeMap.get(fileExt.toLowerCase());
		if(contentType==null||"".equals(contentType)) {
			contentType = "application/octet-stream";
		}
		meta.setContentType(contentType);
		initRequest.setObjectMetadata(meta);
		InitiateMultipartUploadResult initResponse = cosClient.initiateMultipartUpload(initRequest);
		LOGGER.info("UploadId: " + initResponse.getUploadId());
		String uploadId = initResponse.getUploadId();
		final long partSize = Long.parseLong(MemcacheUtil.getDatabaseObj("cos-partSize"));
		// 计算分块数目
		int partCount = (int) (attach.getFileLength() / partSize);
		if (attach.getFileLength() % partSize != 0) {
			partCount++;
		}
		map.put("uploadId", uploadId);
		map.put("partSize", partSize);
		map.put("partCount", partCount);
		map.put("cosKey", attach.getFilePath());
		map.put("contentType", contentType);
		map.put("host", MemcacheUtil.getDatabaseObj(attach.getApplyType()+"-"+Consts.SOURCE_BUCKET)+"."+MemcacheUtil.getDatabaseObj("cos-endpoint"));
		EsCospart cosPart = new EsCospart();
		cosPart.setCosKey(attach.getFilePath());
		cosPart.setFileMd5(attach.getFileMd5());
		cosPart.setPartCount(partCount);
		cosPart.setUploadId(uploadId);
		cosPart.setUserId(attach.getUserId());
		cosPart.setHost(MemcacheUtil.getDatabaseObj(attach.getApplyType()+"-"+Consts.SOURCE_BUCKET)+"."+MemcacheUtil.getDatabaseObj("cos-endpoint"));
		cosPart.setPartNumber(0);
		cosPart.setApplyType(attach.getApplyType());
		JSONObject esObj = JSONObject.fromObject(cosPart);
		EsUtil.addOrUpdatePart(uploadId,esObj.toString());
		return map;
		/*List<PartETag> partETags = new ArrayList<PartETag>();
		int partNumber = 1;
		int partSize = 4 * 1024 * 1024;*/
		/*UploadPartRequest uploadRequest =  new    UploadPartRequest().withsourceBucketName(sourceBucketName).
				 withUploadId(uploadId).withKey(cosKey).withPartNumber(partNumber).
				  withInputStream(partStream).withPartSize(partSize);  
		UploadPartResult uploadPartResult = cosClient.uploadPart(uploadRequest);
		String eTag = uploadPartResult.getETag();  // 获取 part 的 Etag
		partETags.add(new PartETag(partNumber, eTag));*/
	};
	
	public static void CompleteMultipartUploadResult (String key, String uploadId, String appId) {
		ListPartsRequest listPartsRequest = new ListPartsRequest(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET), key, uploadId);
		// 获取上传的所有Part信息
		cosClient = createCosClient();
		PartListing partListing = cosClient.listParts(listPartsRequest);
		List<PartETag> partETags = new ArrayList<>();
		for(PartSummary part : partListing.getParts()) {
			System.out.println(part.getPartNumber());
			partETags.add(new PartETag(part.getPartNumber(), part.getETag()));
		}
		// 完成分块上传
		CompleteMultipartUploadRequest completeMultipartUploadRequest =
				new CompleteMultipartUploadRequest(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET), key, uploadId, partETags);

		cosClient.completeMultipartUpload(completeMultipartUploadRequest);
	}
	
	/**
	 * 初始化cosClient
	 * @return
	 */
	public static COSClient createCosClient() {
		try {
			if(cosClient==null) {
				COSCredentials  cred  = new BasicCOSCredentials(MemcacheUtil.getDatabaseObj("secretId"),MemcacheUtil.getDatabaseObj("secretKey"));
//				COSCredentials  cred  = new BasicCOSCredentials("AKIDaw0sXJg9D1Z4KLai3A1dP0MJJDtVYdpm","xf8RVR9RUHq9IEwOhkY8SYQ4ShgQvBDz");
				ClientConfig clientConfig = new ClientConfig(new Region(MemcacheUtil.getDatabaseObj("cos-region")));
//				ClientConfig clientConfig = new ClientConfig(new Region("ap-shanghai"));
				clientConfig.setConnectionTimeout(10000);
				clientConfig.setSocketTimeout(10000);
				clientConfig.setHttpProtocol(HttpProtocol.https);
				cosClient = new COSClient(cred, clientConfig);
			}
			return cosClient;
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取coskey
	 * @param fileName
	 * @param userId
	 * @return
	 */
	public static String getCosKey(String fileName, String userId, String platformCode) {
		Calendar now = Calendar.getInstance();
        String year = String.valueOf(now.get(Calendar.YEAR));
        String month = String.valueOf(now.get(Calendar.MONTH) + 1);
        String day = String.valueOf(now.get(Calendar.DAY_OF_MONTH));
        String hour = String.valueOf(now.get(Calendar.HOUR_OF_DAY));
        String min = String.valueOf(now.get(Calendar.MINUTE));
        StringBuilder relativeDirPath = new StringBuilder();
        if(StringUtils.isNotBlank(platformCode)) {
        	relativeDirPath.append(platformCode).append("/");
        }
        relativeDirPath.append("gfs_mnt").append("/").append("data1");
        relativeDirPath.append("/").append(year);
        relativeDirPath.append("/").append(month);
        relativeDirPath.append("/").append(day);
        relativeDirPath.append("/").append(hour);
        relativeDirPath.append("/").append(min);
        relativeDirPath.append("/").append(userId);
        relativeDirPath.append("/").append(UUID.randomUUID().toString().replaceAll("-",""));
        relativeDirPath.append("/").append(fileName);
        return relativeDirPath.toString();
	}
	
	public static void sampleUpload(AttachFile attach, InputStream in) throws IOException {
		try {
			String cosKey = getCosKey(attach.getFileName(), attach.getUserId(), attach.getPlatformCode());
			attach.setFilePath(cosKey);
			ObjectMetadata metadata = new ObjectMetadata();
			String contentType = Consts.contentTypeMap.get(attach.getFileExt().toLowerCase());
			if(contentType==null||"".equals(contentType)) {
				contentType = "application/octet-stream";
			}
			metadata.setContentType(contentType);
			metadata.setContentLength(attach.getFileLength());
			PutObjectRequest putObjectRequest = new PutObjectRequest(MemcacheUtil.getDatabaseObj(attach.getApplyType()+"-"+Consts.SOURCE_BUCKET), cosKey, in, metadata);
			cosClient = createCosClient();
			if(cosClient!=null) {
				PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
				System.out.println(putObjectResult);
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			in.close();
		}
	}
	
	public static void partUpload(String appId) throws Exception {
		String cosKey = getCosKey("2222.asf","sz","888888");
		// 初始化分块
		cosClient = createCosClient();
		InitiateMultipartUploadRequest initRequest =
		                new InitiateMultipartUploadRequest(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET), cosKey);
		InitiateMultipartUploadResult initResponse = cosClient.initiateMultipartUpload(initRequest);
		String uploadId = initResponse.getUploadId();
		System.out.println("==========================="+uploadId);
		File partFile = new File("D:\\tmp\\资源\\视频\\2222.asf");
		final long partSize = 1024 * 1024;
		// 计算分块数目
		int partCount = (int) (partFile.length() / partSize);
		if (partFile.length() % partSize != 0) {
			partCount++;
		}
        
		for (int i = 0; i < partCount; i++) {
			// 获取文件流
			FileInputStream fis = new FileInputStream(partFile);
			// 跳到每个分块的开头
			long skipBytes = partSize * i;
			fis.skip(skipBytes);
			// 计算每个分块的大小
			long size = partSize < partFile.length() - skipBytes ? partSize : partFile.length() - skipBytes;
            UploadPartRequest uploadRequest =  new UploadPartRequest().withBucketName(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET)).
   				 withUploadId(uploadId).withKey(cosKey).withPartNumber(i + 1).
   				 withInputStream(fis).withPartSize(size);  
            System.out.println(uploadId);
            UploadPartResult uploadPartResult = cosClient.uploadPart(uploadRequest);
            System.out.println(uploadPartResult.getETag());
            fis.close();
        }
		CompleteMultipartUploadResult(cosKey,uploadId,appId);
	}
	
	public static void main(String[] args) throws Exception {
//		String downloadUrl = getDownloadUrl("4444.png");
//		System.out.println(downloadUrl);
		
		
		
//		String cosKey = getCosKey("2222.asf","sz");
//		// 初始化分块
//		cosClient = createCosClient();
//		InitiateMultipartUploadRequest initRequest =
//		                new InitiateMultipartUploadRequest(sourceBucketName, cosKey);
//		InitiateMultipartUploadResult initResponse = cosClient.initiateMultipartUpload(initRequest);
//		String uploadId = initResponse.getUploadId();
//		System.out.println("==========================="+uploadId);
//		File partFile = new File("D:\\tmp\\资源\\视频\\2222.asf");
//		final long partSize = 1024 * 1024;
//		// 计算分块数目
//		int partCount = (int) (partFile.length() / partSize);
//		if (partFile.length() % partSize != 0) {
//			partCount++;
//		}
//        
//		for (int i = 0; i < partCount; i++) {
//			// 获取文件流
//			FileInputStream fis = new FileInputStream(partFile);
//			// 跳到每个分块的开头
//			long skipBytes = partSize * i;
//			fis.skip(skipBytes);
//			// 计算每个分块的大小
//			long size = partSize < partFile.length() - skipBytes ? partSize : partFile.length() - skipBytes;
//            UploadPartRequest uploadRequest =  new UploadPartRequest().withsourceBucketName(sourceBucketName).
//   				 withUploadId(uploadId).withKey(cosKey).withPartNumber(i + 1).
//   				  withInputStream(fis).withPartSize(size);  
//            System.out.println(uploadId);
//            UploadPartResult uploadPartResult = cosClient.uploadPart(uploadRequest);
//            System.out.println(uploadPartResult.getETag());
//            fis.close();
//        }
//		CompleteMultipartUploadResult(cosKey,uploadId);
		
		
		
		/*COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
		COSSigner signer = new COSSigner();
		//设置过期时间为1个小时
		Date expiredTime = new Date(System.currentTimeMillis() + 3600L * 1000L);
		// 要签名的 key, 生成的签名只能用于对应此key的下载
		String key = "/aaa.txt";
		String sign = signer.buildAuthorizationStr(HttpMethodName.PUT, key, cred, expiredTime);
		System.out.println(sign);*/
		
		
//		ProcessCosMedia("/测试微课.mpg");
//		DescribeInstances();
		String bucketName = "test111-1256736654";
		boolean createSuccess=createBucket(bucketName);
		System.out.println(bucketName+"创建"+createSuccess);
		/*TreeMap<String,Object> commonParams = getCommonParams("GetTaskInfo");
		commonParams.put("vodTaskId", "1255422780-procedurev2-000694ed18b1c10e14db554027e3063et0");
		commonParams.put("Signature",sign(getStringToSign(commonParams),"HK9nDOLAl6D5mETVJ4e8XlmdbKn283lD", "HmacSHA1"));
		String getTaskInfoUrl = getUrl(commonParams);
		System.out.println(getTaskInfoUrl);
		String response = new HttpClient(getTaskInfoUrl).doGet();
		System.out.println(response);
		*/
		/*String destKey = getDestKey("gfs_mnt/data1/2019/3/5/17/35/sz/transform.mp4");
		System.out.println(destKey);*/
		
//		transformVideo("测试微课.mpg");
//		getTask("1255422780-procedurev2-89f853940d9eb4a585a3de55e39feb08t0");
		
		/*TreeMap<String, Object> params = new TreeMap<String, Object>(); // TreeMap可以自动排序
        params.put("Nonce", new Random().nextInt(java.lang.Integer.MAX_VALUE));
        params.put("Timestamp", System.currentTimeMillis() / 1000);
        params.put("SecretId", "AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE"); // 公共参数
        params.put("Action", "DescribeInstances"); // 公共参数
        params.put("Version", "2017-03-12"); // 公共参数
        params.put("Region", MemcacheUtil.getDatabaseObj("cos-region")); // 公共参数
        params.put("Limit", 20); // 业务参数
        params.put("Offset", 0); // 业务参数
        params.put("InstanceIds.0", "ins-09dx96dg"); // 业务参数
        params.put("Signature", sign(getStringToSign(params), "Gu5t9xGARNpq86cd98joQYCN3EXAMPLE", "HmacSHA1")); // 公共参数
        System.out.println(getUrl(params));*/
		/*Map<String, String> headerMap = new HashMap<>();
		headerMap.put("content-type", "");*/
//		getAuthorization("/test/测试视频.mp4","PUT",null,null);
		
//		getSts();
		
//		String downloadUrl = getAuthDownloadUrl("/gfs_mnt/data1/2019/4/8/11/49/be6832f5f25e4e148319f9ef52a9d9e3/2222.png");
//		System.out.println(downloadUrl);
		
	}
	
	/**
	 * 获取带有授权信息的下载地址，设置有效期200年，用来解决下载地址使用cdn加速域名
	 * @param cosKey
	 * @return
	 */
	public static String getAuthDownloadUrl(String cosKey, String appId) {
		GeneratePresignedUrlRequest req =
		        new GeneratePresignedUrlRequest(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET), cosKey, HttpMethodName.GET);
		Date expirationDate = new Date(System.currentTimeMillis() + 200L * 365L * 24L * 3600L * 1000L);
		req.setExpiration(expirationDate);
		// 设置下载时返回的http头
		ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides();
		responseHeaders.setContentDisposition("attachment");
		req.setResponseHeaders(responseHeaders);
		cosClient = createCosClient();
		URL downloadUrl = cosClient.generatePresignedUrl(req);
		String downUrl = downloadUrl.toString();
		downUrl = downUrl.replace(MemcacheUtil.getDatabaseObj("cos-endpoint"), MemcacheUtil.getDatabaseObj("cos-cdn-endpoint"));
		return downUrl;
		/*StringBuffer downloadUrlStr = new StringBuffer("http://").append(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET))
				.append(".").append(MemcacheUtil.getDatabaseObj("cos-cdn-endpoint")).append("/").append(cosKey).append("?response-content-disposition=attachment");
		return downloadUrlStr.toString();*/
	}
	
	public static String getAuthDownloadUrlForPrivate(String cosKey, String appId) {
		GeneratePresignedUrlRequest req =
		        new GeneratePresignedUrlRequest(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET), cosKey, HttpMethodName.GET);
		Date expirationDate = new Date(System.currentTimeMillis() + 200L * 365L * 24L * 3600L * 1000L);
		req.setExpiration(expirationDate);
		// 设置下载时返回的http头
		ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides();
		responseHeaders.setContentDisposition("attachment");
		req.setResponseHeaders(responseHeaders);
		cosClient = createCosClient();
		URL downloadUrl = cosClient.generatePresignedUrl(req);
		String downUrl = downloadUrl.toString();
		downUrl = downUrl.replace(MemcacheUtil.getDatabaseObj("cos-endpoint"), MemcacheUtil.getDatabaseObj("cos-cdn-endpoint"));
		/*StringBuffer downloadUrlStr = new StringBuffer("http://").append(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET))
				.append(".").append(MemcacheUtil.getDatabaseObj("cos-cdn-endpoint")).append("/").append(cosKey).append("?response-content-disposition=attachment");
		return downloadUrlStr.toString();*/
		return downUrl;
	}
	
	/**
	 * 生成一个下载签名
	 * @param cosKey
	 * @return
	 */
	public static String getdownloadAuth(String cosKey) {
		cosKey = getCorrectKey(cosKey);
		COSCredentials cred = new BasicCOSCredentials(MemcacheUtil.getDatabaseObj("secretId"), MemcacheUtil.getDatabaseObj("secretKey"));
		COSSigner signer = new COSSigner();
		//设置过期时间为半个小时
		Date expiredTime = new Date(System.currentTimeMillis() + 1800L * 1000L);
		String sign = signer.buildAuthorizationStr(HttpMethodName.GET, cosKey, cred, expiredTime);
		return sign;
	}
	
	/**
	 * 获取音视频等文件的在线预览地址
	 * @param cosKey
	 * @param appId
	 * @return
	 */
	public static String getAuthPreviewUrl(String cosKey, String appId) {
		GeneratePresignedUrlRequest req =
		        new GeneratePresignedUrlRequest(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.DEST_BUCKET), cosKey, HttpMethodName.GET);
		Date expirationDate = new Date(System.currentTimeMillis() + 50L * 365L * 24L * 3600L * 1000L);
		req.setExpiration(expirationDate);
		cosClient = createCosClient();
		URL previewUrl = cosClient.generatePresignedUrl(req);
		return previewUrl.toString();
	}
	
	public static String getAuthPicPreviewUrl(String cosKey, String appId) {
		GeneratePresignedUrlRequest req =
		        new GeneratePresignedUrlRequest(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET), cosKey, HttpMethodName.GET);
		Date expirationDate = new Date(System.currentTimeMillis() + 50L * 365L * 24L * 3600L * 1000L);
		req.setExpiration(expirationDate);
		cosClient = createCosClient();
		URL previewUrl = cosClient.generatePresignedUrl(req);
		return previewUrl.toString();
	}
	
	/**
	 * 获取永久有效的下载地址
	 * @param cosKey
	 * @return
	 */
	public static String getDownloadUrl(String cosKey, String appId) {
		StringBuffer downloadUrlStr = new StringBuffer("http://").append(MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET))
				.append(".").append(MemcacheUtil.getDatabaseObj("cos-v4-endpoint")).append("/").append(cosKey);	
		return downloadUrlStr.toString();
	}
	/**
	 * 获取授权信息
	 * @param cosKey
	 * @param headerMap
	 * @return
	 */
	public static String getAuthorization(String cosKey, Map<String, String> headerMap, Map<String, String> paramMap) {
		cosKey = getCorrectKey(cosKey);
		COSCredentials cred = new BasicCOSCredentials(MemcacheUtil.getDatabaseObj("secretId"),MemcacheUtil.getDatabaseObj("secretKey"));
		COSSigner signer = new COSSigner();
		//设置过期时间为1个小时
		Date expiredTime = new Date(System.currentTimeMillis() + 3600L * 1000L);
		String sign = "";
		if(null==headerMap&&null==paramMap) {
			sign = signer.buildAuthorizationStr(HttpMethodName.PUT, cosKey, cred, expiredTime);
		}else {
			sign = signer.buildAuthorizationStr(HttpMethodName.PUT, cosKey, headerMap, paramMap, cred, expiredTime);
		}
		System.out.println(sign);
		return sign;
	}

	public static TreeMap<String, Object> getNewCommonParams(String action, String version){
		TreeMap<String, Object> commonParams = new TreeMap<String, Object>();
		commonParams.put("Action", action);   //接口指令名称
		commonParams.put("Region", MemcacheUtil.getDatabaseObj("cos-region"));     //腾讯云开通区域，sh表示上海
//		commonParams.put("Region", "ap-shanghai");
		commonParams.put("Timestamp", System.currentTimeMillis() / 1000);    //当前UNIX时间戳
		commonParams.put("Nonce", new Random().nextInt(java.lang.Integer.MAX_VALUE));        //随机正整数，与 Timestamp 联合起来, 用于防止重放攻击
		commonParams.put("SecretId", MemcacheUtil.getDatabaseObj("secretId"));     //腾讯云平台上申请的SecretId
//		commonParams.put("SecretId", "AKIDkGXZMDyCKCpCNILiYAWkjTyDH5cu9oOk");
		commonParams.put("Version", version);
		return commonParams;
	}

	public static TreeMap<String, Object> getCommonParams(String action){
		TreeMap<String, Object> commonParams = new TreeMap<String, Object>();
		commonParams.put("Action", action);   //接口指令名称
		commonParams.put("Region", MemcacheUtil.getDatabaseObj("cos-region"));     //腾讯云开通区域，sh表示上海
//		commonParams.put("Region", "ap-shanghai");
		commonParams.put("Timestamp", System.currentTimeMillis() / 1000);    //当前UNIX时间戳
		commonParams.put("Nonce", new Random().nextInt(java.lang.Integer.MAX_VALUE));        //随机正整数，与 Timestamp 联合起来, 用于防止重放攻击
		commonParams.put("SecretId", MemcacheUtil.getDatabaseObj("secretId"));     //腾讯云平台上申请的SecretId
//		commonParams.put("SecretId", "AKIDkGXZMDyCKCpCNILiYAWkjTyDH5cu9oOk");
		commonParams.put("Version", "2017-03-12");
		return commonParams;
	}
	
	public static String sign(String s, String key, String method) throws Exception {
        Mac mac = Mac.getInstance(method);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(CHARSET), mac.getAlgorithm());
        mac.init(secretKeySpec);
        byte[] hash = mac.doFinal(s.getBytes(CHARSET));
        return DatatypeConverter.printBase64Binary(hash);
    }
	
	public static String getStringToSign(TreeMap<String, Object> params) {
        StringBuilder s2s = new StringBuilder("GETvod.api.qcloud.com/v2/index.php?");
        // 签名时要求对参数进行字典排序，此处用TreeMap保证顺序
        for (String k : params.keySet()) {
            s2s.append(k).append("=").append(params.get(k).toString()).append("&");
        }
        return s2s.toString().substring(0, s2s.length() - 1);
    }

	public static String getStringToSignNew(TreeMap<String, Object> params) {
		StringBuilder s2s = new StringBuilder("GETmps.tencentcloudapi.com/?");
		// 签名时要求对参数进行字典排序，此处用TreeMap保证顺序
		for (String k : params.keySet()) {
			s2s.append(k).append("=").append(params.get(k).toString()).append("&");
		}
		return s2s.toString().substring(0, s2s.length() - 1);
	}

	public static String getUrl(TreeMap<String, Object> params) throws UnsupportedEncodingException {
        StringBuilder url = new StringBuilder(vodUrl);
        // 实际请求的url中对参数顺序没有要求
        for (String k : params.keySet()) {
            // 需要对请求串进行urlencode，由于key都是英文字母，故此处仅对其value进行urlencode
            url.append(k).append("=").append(URLEncoder.encode(params.get(k).toString(), CHARSET)).append("&");
        }
        return url.toString().substring(0, url.length() - 1);
    }

	public static String getUrlNew(TreeMap<String, Object> params) throws UnsupportedEncodingException {
		StringBuilder url = new StringBuilder(vodUrlNew);
		// 实际请求的url中对参数顺序没有要求
		for (String k : params.keySet()) {
			// 需要对请求串进行urlencode，由于key都是英文字母，故此处仅对其value进行urlencode
			url.append(k).append("=").append(URLEncoder.encode(params.get(k).toString(), "UTF-8")).append("&");
		}
		return url.toString().substring(0, url.length() - 1);
	}

	public static void getTaskInfo(String vodTaskId) throws Exception {
		TreeMap<String, Object> commonParams = getCommonParams("GetTaskInfo");
		commonParams.put("vodTaskId", vodTaskId);
		commonParams.put("Signature",sign(getStringToSign(commonParams),MemcacheUtil.getDatabaseObj("secretKey"), "HmacSHA1"));
		String getTaskInfoUrl = getUrl(commonParams);
		System.out.println(getTaskInfoUrl);
		String response = new HttpClient(getTaskInfoUrl).doGet();
		System.out.println(response);
	}

	/**
	 * 新版转码接口
	 * @param cosKey
	 * @param type
	 * @param appId
	 * @param fid
	 * @date 2020-4-30
	 * @return
	 * @throws Exception
	 */
	public static String ProcessMedia(String cosKey, int type, String appId, String fid) throws Exception {
		String queueName;  //队列名称
		if(Consts.DEV_AVTIVE_PPUBLIC.equals(Consts.getProfileActive())) {
			//正式环境
			queueName = MemcacheUtil.getDatabaseObj(Consts.CMQ_ATTACHMENT_VIDEO_FINISH);
		} else {
			//测试环境
			queueName = MemcacheUtil.getDatabaseObj(Consts.CMQ_ATTACHMENT_VIDEO_FINISH_TEST);
			LOGGER.info("测试环境队列名称：" + queueName);
		}
		cosKey = getCorrectKey(cosKey);
		String destKey = getDestKey(cosKey)+fid+"/";
		TreeMap<String, Object> commonParams = getNewCommonParams("ProcessMedia","2019-06-12");
		commonParams.put("InputInfo.Type", "COS");
		commonParams.put("InputInfo.CosInputInfo.Bucket", MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET));
		commonParams.put("InputInfo.CosInputInfo.Region", MemcacheUtil.getDatabaseObj("cos-region"));
		commonParams.put("InputInfo.CosInputInfo.Object", cosKey);
		commonParams.put("OutputStorage.Type", "COS");
		commonParams.put("OutputStorage.CosOutputStorage.Bucket", MemcacheUtil.getDatabaseObj(appId+"-"+Consts.DEST_BUCKET));
		commonParams.put("OutputStorage.CosOutputStorage.Region", MemcacheUtil.getDatabaseObj("cos-region"));
		commonParams.put("OutputDir", destKey);
		if(type==1) {
			commonParams.put("MediaProcessTask.TranscodeTaskSet.0.Definition", 116527);   //新版设置转码模板
			commonParams.put("MediaProcessTask.SnapshotByTimeOffsetTaskSet.0.Definition", 10);
			commonParams.put("MediaProcessTask.SnapshotByTimeOffsetTaskSet.0.TimeOffsetSet.0", 0);
		}else if(type==2) {
			commonParams.put("MediaProcessTask.TranscodeTaskSet.0.Definition", 1010);
		}
		commonParams.put("TaskNotifyConfig.CmqModel", "Queue");
		commonParams.put("TaskNotifyConfig.CmqRegion", "sh");
		commonParams.put("TaskNotifyConfig.QueueName", queueName);
		commonParams.put("TaskNotifyConfig.NotifyMode", "Finish");
		commonParams.put("SessionContext", fid);
		commonParams.put("Signature",sign(getStringToSignNew(commonParams),MemcacheUtil.getDatabaseObj("secretKey"), "HmacSHA1"));
		String processCosMediaUrl = getUrlNew(commonParams);
		LOGGER.info(processCosMediaUrl);
		String response = new HttpClient(processCosMediaUrl).doGet();
		JSONObject json = JSONObject.fromObject(response);
		LOGGER.info(response);
		JSONObject respon = json.optJSONObject("Response");
		String taskId = respon.optString("TaskId");
		if(StringUtils.isNotBlank(taskId)) {
			return taskId;
		}else {
			LOGGER.error(response);
			return null;
		}
	}

	public static String ProcessCosMedia(String cosKey, int type, String appId, String fid) throws Exception {
		cosKey = getCorrectKey(cosKey);
		String destKey = getDestKey(cosKey)+fid+"/";
		TreeMap<String, Object> commonParams = getCommonParams("ProcessCosMedia");
		commonParams.put("input.bucket", MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET));
		commonParams.put("input.path", cosKey);
		commonParams.put("input.region", MemcacheUtil.getDatabaseObj("cos-region"));
		commonParams.put("output.bucket", MemcacheUtil.getDatabaseObj(appId+"-"+Consts.DEST_BUCKET));
		commonParams.put("output.dir", destKey);
		commonParams.put("output.region", MemcacheUtil.getDatabaseObj("cos-region"));
		if(type==1) {
			commonParams.put("mediaProcess.transcode.definition.0", 116619);    //默认模板30
			commonParams.put("mediaProcess.snapshotByTimeOffset.definition.0", 10);
			commonParams.put("mediaProcess.snapshotByTimeOffset.timeOffset.0", 0);
		}else if(type==2) {
			commonParams.put("mediaProcess.transcode.definition.0", 1010);
		}
		commonParams.put("Signature",sign(getStringToSign(commonParams),MemcacheUtil.getDatabaseObj("secretKey"), "HmacSHA1"));
		String processCosMediaUrl = getUrl(commonParams);
		System.out.println(processCosMediaUrl);
		String response = new HttpClient(processCosMediaUrl).doGet();
		JSONObject json = JSONObject.fromObject(response);
		System.out.println(response);
		int code = json.optInt("code");
		if(code==0) {
			return json.optString("vodTaskId");
		}else {
			LOGGER.error(response);
			return null;
		}
	}
	
	public static void DescribeInstances() throws Exception {
		TreeMap<String, Object> commonParams = getCommonParams("DescribeInstances");
		commonParams.put("Limit", 20);
		commonParams.put("Offset", 0);
		commonParams.put("InstanceIds.0", "ins-09dx96dg");
		commonParams.put("Signature",sign(getStringToSign(commonParams),MemcacheUtil.getDatabaseObj("secretKey"), "HmacSHA1"));
		String processCosMediaUrl = getUrl(commonParams);
		System.out.println(processCosMediaUrl);
		String response = new HttpClient(processCosMediaUrl).doGet();
		System.out.println(response);
	}
	
	
	public static byte[] sign256(byte[] key, String msg) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
        mac.init(secretKeySpec);
        return mac.doFinal(msg.getBytes(CHARSET));
    }
	
	public static Map<String, String> getAuthorization(String httpRequestMethod, String action, Map<String, Object> param, Map<String, Object> header) throws Exception {
		String service = "cvm";
        String host = "cvm.tencentcloudapi.com";
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 注意时区，否则容易出错
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));
		
		// ************* 步骤 1：拼接规范请求串 *************
        StringBuilder canonicalQueryString = new StringBuilder();
        StringBuilder canonicalHeaders = new StringBuilder();
        StringBuilder signedHeaders = new StringBuilder();
        String hashedRequestPayload = "";
        String canonicalUri = "/";
        if("GET".equals(httpRequestMethod)) {
        	for (String k : header.keySet()) {
        		canonicalQueryString.append(k+"=").append(header.get(k).toString()+"&");
            }
        	
        }else if("POST".equals(httpRequestMethod)) {
        	canonicalQueryString.append("");
        }
        for (String k : header.keySet()) {
            canonicalHeaders.append(k+":").append(header.get(k).toString()+"\n");
        }
        for (String k : header.keySet()) {
        	signedHeaders.append(k+";");
        }
        if("GET".equals(httpRequestMethod)) {
        	hashedRequestPayload = DigestUtils.sha256Hex("");
        	
        }else if("POST".equals(httpRequestMethod)) {
        	JSONObject json = JSONObject.fromObject(param);
        	hashedRequestPayload = DigestUtils.sha256Hex(json.toString());
        }
        String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString.toString() + "\n"
                + canonicalHeaders.toString() + "\n" + signedHeaders.toString() + "\n" + hashedRequestPayload;
        System.out.println(canonicalRequest);
        
        // ************* 步骤 2：拼接待签名字符串 *************
        String credentialScope = date + "/" + service + "/" + "tc3_request";
        String hashedCanonicalRequest = DigestUtils.sha256Hex(canonicalRequest.getBytes(CHARSET));
        String stringToSign = algorithm + "\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
        System.out.println(stringToSign);
        
        // ************* 步骤 3：计算签名 *************
        byte[] secretDate = sign256(("TC3" + MemcacheUtil.getDatabaseObj("secretKey")).getBytes(CHARSET), date);
        byte[] secretService = sign256(secretDate, service);
        byte[] secretSigning = sign256(secretService, "tc3_request");
        String signature = DatatypeConverter.printHexBinary(sign256(secretSigning, stringToSign)).toLowerCase();
        System.out.println(signature);
        
        // ************* 步骤 4：拼接 Authorization *************
        String authorization = algorithm + " " + "Credential=" + MemcacheUtil.getDatabaseObj("secretId") + "/" + credentialScope + ", "
                + "SignedHeaders=" + signedHeaders.toString() + ", " + "Signature=" + signature;
        System.out.println(authorization);
        
        TreeMap<String, String> headers = new TreeMap<String, String>();
        headers.put("Authorization", authorization);
        headers.put("Host", host);
        headers.put("X-TC-Action", action);
        headers.put("X-TC-Timestamp", timestamp);
        headers.put("X-TC-Version", version);
        headers.put("X-TC-Region", MemcacheUtil.getDatabaseObj("cos-region"));
        return headers;
	}
	
	public static String apiAuth(String HttpURI, Map<String, String> param, Map<String, String> header) {
		String HttpMethod = "put";
		HttpURI = getCorrectKey(HttpURI);
		long timestamp = System.currentTimeMillis() / 1000;
		String signTime = String.valueOf(timestamp)+";"+ String.valueOf(timestamp+3600*1000);
		String signKey = HmacUtils.hmacSha1Hex(MemcacheUtil.getDatabaseObj("secretKey"), signTime);
		
		TreeMap<String, String> sortedHeaders = new TreeMap<>();
        TreeMap<String, String> sortedParams = new TreeMap<>();

        sortedHeaders.putAll(header);
        sortedParams.putAll(param);
		
		String HttpParameters = getString(sortedHeaders);
		String HttpHeaders = getString(sortedHeaders);
		String HttpString = HttpMethod +"\n"+HttpURI+"\n"+HttpParameters+"\n"+HttpHeaders+"\n";
		String StringToSign = "sha1\n"+signTime+"\n"+DigestUtils.sha1Hex(HttpString)+"\n";
		String Signature =  HmacUtils.hmacSha1Hex(signKey, StringToSign);
		System.out.println(Signature);
		
		String qHeaderListStr = buildSignMemberStr(sortedHeaders);
        String qUrlParamListStr = buildSignMemberStr(sortedParams);
		
		String authoriationStr = new StringBuilder().append("q-sign-algorithm").append("=")
                .append("sha1").append("&").append("q-ak").append("=")
                .append(MemcacheUtil.getDatabaseObj("secretId")).append("&").append("q-sign-time").append("=")
                .append(signTime).append("&").append("q-key-time").append("=").append(signTime)
                .append("&").append("q-header-list").append("=").append(qHeaderListStr).append("&")
                .append("q-url-param-list").append("=").append(qUrlParamListStr).append("&")
                .append("q-signature").append("=").append(Signature).toString();
        return authoriationStr;
	}
	
	public static String getString(Map<String, String> kVMap) {
		
		StringBuilder strBuilder = new StringBuilder();
        boolean seeOne = false;
        for (Entry<String, String> entry : kVMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            String lowerKey = key.toLowerCase();
            String encodeKey = UrlEncoderUtils.encode(lowerKey);
            String encodedValue = "";
            if (value != null) {
                encodedValue = UrlEncoderUtils.encode(value);
            }
            if (!seeOne) {
                seeOne = true;
            } else {
                strBuilder.append("&");
            }
            strBuilder.append(encodeKey).append("=").append(encodedValue);
        }
        return strBuilder.toString();
	}
	
	public static String buildSignMemberStr(Map<String, String> signHeaders) {
        StringBuilder strBuilder = new StringBuilder();
        boolean seenOne = false;
        for (String key : signHeaders.keySet()) {
            if (!seenOne) {
                seenOne = true;
            } else {
                strBuilder.append(";");
            }
            strBuilder.append(key.toLowerCase());
        }
        return strBuilder.toString();
    }
	
	
	public static void transformVideo(String cosKey, String appId) {
		TreeMap<String, Object> config = new TreeMap<String, Object>();
		config.put("SecretId", MemcacheUtil.getDatabaseObj("secretId"));
		config.put("SecretKey", MemcacheUtil.getDatabaseObj("secretKey"));
		/* 请求方法类型 POST、GET */
		config.put("RequestMethod", "GET");
		/* 区域参数，可选: gz:广州; sh:上海; hk:香港; ca:北美;等。 */
		config.put("DefaultRegion", "sh");

		/*
		 * 你将要使用接口所在的模块，可以从 官网->云api文档->XXXX接口->接口描述->域名
		 * 中获取，比如域名：cvm.api.qcloud.com，module就是 new Cvm()。
		 */
		/*
		 * 示例：DescribeInstances
		 * 的api文档地址：http://www.qcloud.com/wiki/v2/DescribeInstances
		 */
		QcloudApiModuleCenter module = new QcloudApiModuleCenter(new Vod(),
				config);

		TreeMap<String, Object> params = new TreeMap<String, Object>();
		/* 将需要输入的参数都放入 params 里面，必选参数是必填的。 */
		/* DescribeInstances 接口的部分可选参数如下 */
		params.put("input.bucket", MemcacheUtil.getDatabaseObj(appId+"-"+Consts.SOURCE_BUCKET));
		params.put("input.path", cosKey);
		params.put("input.region", MemcacheUtil.getDatabaseObj("cos-region"));
		params.put("output.bucket", MemcacheUtil.getDatabaseObj(appId+"-"+Consts.DEST_BUCKET));
		params.put("output.dir", "/test/");
		params.put("mediaProcess.transcode.definition.0", 30);
		params.put("mediaProcess.snapshotByTimeOffset.definition.0", 10);
		params.put("mediaProcess.snapshotByTimeOffset.timeOffset.0", 0);
		/*在这里指定所要用的签名算法，不指定默认为HmacSHA1*/
		//params.put("SignatureMethod", "HmacSHA256");
		
		/* generateUrl方法生成请求串,可用于调试使用 */
		//System.out.println(module.generateUrl("DescribeInstances", params));
		String result = null;
		try {
			/* call 方法正式向指定的接口名发送请求，并把请求参数params传入，返回即是接口的请求结果。 */
			result = module.call("ProcessCosMedia", params);
			System.out.println(result);
		} catch (Exception e) {
			System.out.println("error..." + e.getMessage());
		}
	}
	
	public static void getTask(String taskId) {
		TreeMap<String, Object> config = new TreeMap<String, Object>();
		config.put("SecretId", MemcacheUtil.getDatabaseObj("secretId"));
		config.put("SecretKey", MemcacheUtil.getDatabaseObj("secretKey"));
		/* 请求方法类型 POST、GET */
		config.put("RequestMethod", "GET");
		/* 区域参数，可选: gz:广州; sh:上海; hk:香港; ca:北美;等。 */
		config.put("DefaultRegion", "sh");

		/*
		 * 你将要使用接口所在的模块，可以从 官网->云api文档->XXXX接口->接口描述->域名
		 * 中获取，比如域名：cvm.api.qcloud.com，module就是 new Cvm()。
		 */
		/*
		 * 示例：DescribeInstances
		 * 的api文档地址：http://www.qcloud.com/wiki/v2/DescribeInstances
		 */
		QcloudApiModuleCenter module = new QcloudApiModuleCenter(new Vod(),
				config);

		TreeMap<String, Object> params = new TreeMap<String, Object>();
		/* 将需要输入的参数都放入 params 里面，必选参数是必填的。 */
		/* DescribeInstances 接口的部分可选参数如下 */
		params.put("vodTaskId", taskId);
		/*在这里指定所要用的签名算法，不指定默认为HmacSHA1*/
		//params.put("SignatureMethod", "HmacSHA256");
		
		/* generateUrl方法生成请求串,可用于调试使用 */
		//System.out.println(module.generateUrl("DescribeInstances", params));
		String result = null;
		try {
			/* call 方法正式向指定的接口名发送请求，并把请求参数params传入，返回即是接口的请求结果。 */
			result = module.call("GetTaskInfo", params);
			System.out.println(result);
		} catch (Exception e) {
			System.out.println("error..." + e.getMessage());
		}
	}
	
	public static String getCorrectKey(String cosKey) {
		if("".equals(cosKey)||cosKey==null) {
			cosKey = "/";
		}else {
			if(cosKey.startsWith("/")) {
				return cosKey;
			}else {
				cosKey = "/"+cosKey;
			}
		}
		return cosKey;
	}
	
	public static String getDestKey(String cosKey) {
		if(cosKey.lastIndexOf("/")>-1) {
			String destKey = cosKey.substring(0, cosKey.lastIndexOf("/")+1);
			System.out.println(destKey);
			return getCorrectKey(destKey);
		}else {
			return getCorrectKey(cosKey);
		}
	}
	
	public static Map<String, String> getSts(String buketName, String region){
		try {
			TreeMap<String, Object> config = new TreeMap<String, Object>();
			// 替换为您的 SecretId
			config.put("SecretId", MemcacheUtil.getDatabaseObj("secretId"));
			// 替换为您的 SecretKey
			config.put("SecretKey", MemcacheUtil.getDatabaseObj("secretKey"));

			// 临时密钥有效时长，单位是秒
			config.put("durationSeconds", 1800);

			// 换成您的 bucket
			config.put("bucket", buketName);
			// 换成 bucket 所在地区
			config.put("region", region);

			// 这里改成允许的路径前缀，可以根据自己网站的用户登录态判断允许上传的目录，例子：* 或者 doc/* 或者 picture.jpg
			config.put("allowPrefix", "*");

			// 密钥的权限列表。简单上传、表单上传和分片上传需要以下的权限，其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
			String[] allowActions = new String[] {
					// 简单上传
					"name/cos:PutObject",
					// 表单上传、小程序上传
					"name/cos:PostObject",
					// 分片上传
					"name/cos:InitiateMultipartUpload",
					"name/cos:ListMultipartUploads",
					"name/cos:ListParts",
					"name/cos:UploadPart",
					"name/cos:CompleteMultipartUpload",
					// 对象查询
					"name/cos:HeadObject",
					//查询存储桶对象列表
					"name/cos:GetBucket",
					//下载对象
					"name/cos:GetObject"
			};
			config.put("allowActions", allowActions);

			Map<String, String> map = MapUtil.newHashMap();
			org.json.JSONObject credential = CosStsClient.getCredential(config);
			org.json.JSONObject credentials = credential.optJSONObject("credentials");
			map.put("tmpSecretId", credentials.optString("tmpSecretId"));
			map.put("tmpSecretKey", credentials.optString("tmpSecretKey"));
			map.put("sessionToken", credentials.optString("sessionToken"));
			map.put("expiration", credential.optString("expiration"));
			//成功返回临时密钥信息，如下打印密钥信息
			MemcacheUtil.putObj(buketName+region+"TempCredential", map, 1200);
			return map;
		} catch (Exception e) {
			//失败抛出异常
			throw new IllegalArgumentException("no valid secret !");
		}
	}


	/**
	 * 创建桶
	 * @param bucketName
	 */
	public static boolean createBucket(String bucketName){
		cosClient = createCosClient();
		CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
 		// 设置 bucket 的权限为 Private(私有读写), 其他可选有公有读私有写, 公有读写
		createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
		Bucket newBucket=cosClient.createBucket(createBucketRequest);
		return newBucket != null;
	}

	public static boolean doesExists(String cosKey, String bucketName){
		cosClient = createCosClient();
		return cosClient.doesObjectExist(bucketName,getCorrectKey(cosKey));
	}

	/**
	 * 复制对象存储
	 * @param
	 */
	public static void copyCos(String srcName, String srckey,String destName, String destkey ){

		TransferManager transferManager = createTransferManager();
		Region srcBucketRegion = new Region("ap-shanghai");
		// 复制的源桶，命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
		// 复制的源文件路径

		// 复制的目的桶名, 命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
		// 复制的目的文件路径
		CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, srcName,
				srckey, destName, destkey);
		try {
			Copy copy = transferManager.copy(copyObjectRequest);
			// 高级接口会返回一个异步结果 Copy
			// 可同步的调用 waitForCopyResult 等待复制结束, 成功返回 CopyResult, 失败抛出异常
			CopyResult copyResult = copy.waitForCopyResult();
			System.out.println(copyResult.getRequestId());
		} catch (CosServiceException e) {
			e.printStackTrace();
		} catch (CosClientException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}

	// 创建 TransferManager 实例，这个实例用来后续调用高级接口
	public static TransferManager createTransferManager() {
		// 创建一个 COSClient 实例，这是访问 COS 服务的基础实例。
		// 这里创建的 cosClient 是以复制的目的端信息为基础的
		// 详细代码参见本页: 简单操作 -> 创建 COSClient
		cosClient = createCosClient();

		// 自定义线程池大小，建议在客户端与 COS 网络充足（例如使用腾讯云的 CVM，同地域上传 COS）的情况下，设置成16或32即可，可较充分的利用网络资源
		// 对于使用公网传输且网络带宽质量不高的情况，建议减小该值，避免因网速过慢，造成请求超时。
		ExecutorService threadPool = Executors.newFixedThreadPool(32);

		// 传入一个 threadpool, 若不传入线程池，默认 TransferManager 中会生成一个单线程的线程池。
		TransferManager transferManager = new TransferManager(cosClient, threadPool);

		// 设置高级接口的配置项
		// 分块复制阈值和分块大小分别为 5MB 和 1MB
		TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
		transferManagerConfiguration.setMultipartCopyThreshold(5*1024*1024);
		transferManagerConfiguration.setMultipartCopyPartSize(1*1024*1024);
		transferManager.setConfiguration(transferManagerConfiguration);

		return transferManager;
	}


	/**
	 * 恢复归档对象
	 * @param
	 */
	public static void restoreCos(String srcBucketName, String srcKey){
		cosClient = createCosClient();
// 设置 restore 得到的临时副本过期天数为1天
		RestoreObjectRequest restoreObjectRequest = new RestoreObjectRequest(srcBucketName, srcKey, 5);
// 设置恢复模式为 Standard，其他的可选模式包括 Expedited 和 Bulk。若恢复归档存储类型数据，则支持上述三种恢复模式，选择不同恢复模式，在费用和恢复速度上不一样。若恢复深度归档存储类型数据，则仅支持 Standard 和 Bulk 恢复模式
		CASJobParameters casJobParameters = new CASJobParameters();
		casJobParameters.setTier(Tier.Standard);
		restoreObjectRequest.setCASJobParameters(casJobParameters);
		try {
			cosClient.restoreObject(restoreObjectRequest);
		} catch (CosServiceException e) {
			e.printStackTrace();
		} catch (CosClientException e) {
			e.printStackTrace();
		}
	}



	/**
	 * 复制对象存储
	 * @param
	 */
	public static void copyCos(String bucketName,String key,String storeType ){
		if(StringUtils.isBlank(storeType)){
			storeType = "DEEP_ARCHIVE";
		}
		TransferManager transferManager = createTransferManager();
		Region srcBucketRegion = new Region("ap-shanghai");
		// 复制的源桶，命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
		// 复制的源文件路径

		// 复制的目的桶名, 命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
		// 复制的目的文件路径
		CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, bucketName,
				key, bucketName, key);
		copyObjectRequest.setStorageClass(storeType);
		try {
			Copy copy = transferManager.copy(copyObjectRequest);
			// 高级接口会返回一个异步结果 Copy
			// 可同步的调用 waitForCopyResult 等待复制结束, 成功返回 CopyResult, 失败抛出异常
			CopyResult copyResult = copy.waitForCopyResult();
			System.out.println("复制结果："+copyResult.getRequestId());
		} catch (CosServiceException e) {
			e.printStackTrace();
		} catch (CosClientException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}
}
